package com.ukefu.webim.web.handler.apps.bpm;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.snaker.engine.SnakerEngineFacets;
import org.snaker.engine.SnakerHelper;
import org.snaker.engine.helper.StreamHelper;
import org.snaker.engine.model.ProcessModel;
import org.snaker.engine.parser.ModelParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.ukefu.core.UKDataContext;
import com.ukefu.util.Menu;
import com.ukefu.webim.service.repository.MetadataRepository;
import com.ukefu.webim.service.repository.ProcessContentRepository;
import com.ukefu.webim.web.handler.Handler;
import com.ukefu.webim.web.model.ProcessContent;

@Controller
@RequestMapping("/apps/bpm")
public class BpmController extends Handler{
	
	@Autowired
	private ProcessContentRepository processContentRes ;
	
	@Autowired
	private MetadataRepository metadataRes ;
	
	@Autowired
	private SnakerEngineFacets facets;
	
    @RequestMapping("/index")
    @Menu(type = "bpm" , subtype = "bpm" , access = false)
    public ModelAndView index(ModelMap map , HttpServletRequest request) {
    	map.addAttribute("processList", processContentRes.findByOrgi(super.getOrgi(request) , new PageRequest(super.getP(request), super.getPs(request)))) ;
    	return request(super.createAppsTempletResponse("/apps/business/bpm/index"));
    }
    
    
    @RequestMapping("/add")
    @Menu(type = "bpm" , subtype = "bpm" , access = false )
    public ModelAndView add(ModelMap map , HttpServletRequest request) {
        return request(super.createRequestPageTempletResponse("/apps/business/bpm/add"));
    }
    
    @RequestMapping("/save")
    @Menu(type = "bpm" , subtype = "bpm" , access = false)
    public ModelAndView save(HttpServletRequest request ,@Valid ProcessContent processContent) throws NoSuchAlgorithmException {
    	processContent.setOrgi(super.getOrgi(request));
    	processContent.setCreater(super.getUser(request).getId());
    	processContent.setCreatetime(new Date());
    	processContent.setProcesstype(UKDataContext.ProcessType.WORKORDER.toString());
    	processContent.setPublished(false);
    	processContentRes.save(processContent) ;
    	return request(super.createRequestPageTempletResponse("redirect:/apps/bpm/index.html"));
    }
    
    @RequestMapping("/delete")
    @Menu(type = "bpm" , subtype = "bpm")
    public ModelAndView delete(ModelMap map , HttpServletRequest request , @Valid String id) {
    	if(!StringUtils.isBlank(id)){
    		ProcessContent process = processContentRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    		processContentRes.delete(process);
    		if(!StringUtils.isBlank(process.getProcessid())){
    			org.snaker.engine.entity.Process bpmProcess = facets.getEngine().process().getProcessById(process.getProcessid()) ;
    			if(bpmProcess != null){
    				facets.getEngine().process().cascadeRemove(process.getProcessid());
    			}
    		}
    	}
        return request(super.createRequestPageTempletResponse("redirect:/apps/bpm/index.html"));
    }
    
    @RequestMapping("/edit")
    @Menu(type = "bpm" , subtype = "bpm" , access = false )
    public ModelAndView edit(ModelMap map , HttpServletRequest request , @Valid String id) {
    	map.addAttribute( "processContent" , processContentRes.findByIdAndOrgi(id,super.getOrgi(request))) ;
        return request(super.createRequestPageTempletResponse("/apps/business/bpm/edit"));
    }
    
    @RequestMapping("/update")
    @Menu(type = "bpm" , subtype = "bpm" , access = false)
    public ModelAndView update(HttpServletRequest request ,@Valid ProcessContent processContent) {
    	ProcessContent oldProcessContent = processContentRes.findByIdAndOrgi(processContent.getId(), super.getOrgi(request)) ;
    	if(oldProcessContent!=null){
    		oldProcessContent.setTitle(processContent.getTitle());
    		oldProcessContent.setName(processContent.getName());
    		oldProcessContent.setProcesstype(UKDataContext.ProcessType.WORKORDER.toString());
    		oldProcessContent.setUpdatetime(new Date());
    		processContentRes.save(oldProcessContent) ;
    	}
    	return request(super.createRequestPageTempletResponse("redirect:/apps/bpm/index.html"));
    }
    
    @RequestMapping("/design")
    @Menu(type = "bpm" , subtype = "bpm" , access = false)
    public ModelAndView design(ModelMap map , HttpServletRequest request , @Valid String id) throws UnsupportedEncodingException {
    	ProcessContent process = processContentRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	map.addAttribute( "processContent" , process) ;
    	ProcessModel model = getModel(process);
    	if(model!=null){
	    	String json = SnakerHelper.getModelJson(model);
	    	map.addAttribute("processcontent",json);
    	}else{
    		map.addAttribute("processcontent","");
    	}
    	return request(super.createAppsTempletResponse("/apps/business/bpm/design"));
    }
    
    @RequestMapping("/design/save")
    @Menu(type = "bpm" , subtype = "bpm" , access = false)
    public ModelAndView designsave(HttpServletRequest request ,@Valid ProcessContent processContent) throws NoSuchAlgorithmException {
    	if(!StringUtils.isBlank(processContent.getId()) && !StringUtils.isBlank(processContent.getContent())){
    		ProcessContent pc = processContentRes.findByIdAndOrgi(processContent.getId(),super.getOrgi(request)) ;
    		pc.setContent(processContent.getContent());
     		processContentRes.save(pc) ;
    	}
    	return request(super.createRequestPageTempletResponse("/public/success"));
    }
    
    @RequestMapping(value="/deploy")
    @Menu(type = "bpm" , subtype = "bpm" , access = false)
    public ModelAndView deploy(HttpServletRequest request , @Valid String id){  
    	ProcessContent process = processContentRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	if(process!=null){
    		process.setProcessid(facets.getEngine().process().deploy(StreamHelper.getStreamFromString(SnakerHelper.convertXml(process.getContent())), super.getUser(request).getUsername()));
    		process.setPublished(true);
    		processContentRes.save(process) ;
    	}
    	return request(super.createRequestPageTempletResponse("redirect:/apps/bpm/index.html"));
    }
    
    @RequestMapping(value="/redeploy")
    @Menu(type = "bpm" , subtype = "bpm" , access = false)
    public ModelAndView redeploy(HttpServletRequest request , @Valid String id){  
    	ProcessContent process = processContentRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	if(process!=null && !StringUtils.isBlank(process.getProcessid())){
    		org.snaker.engine.entity.Process snakerProcess = facets.getEngine().process().getProcessById(process.getProcessid()) ;
    		if(snakerProcess!=null){
    			facets.getEngine().process().redeploy(process.getProcessid() , StreamHelper.getStreamFromString(SnakerHelper.convertXml(process.getContent()))) ;
    		}else{
    			process.setProcessid(facets.getEngine().process().deploy(StreamHelper.getStreamFromString(SnakerHelper.convertXml(process.getContent())), super.getUser(request).getUsername()));
    		}
    		process.setPublished(true);
    		processContentRes.save(process) ;
    	}
    	return request(super.createRequestPageTempletResponse("redirect:/apps/bpm/index.html"));
    }
    
    private ProcessModel getModel(ProcessContent process) throws UnsupportedEncodingException{
    	ProcessModel model = null ;
    	if(process.getContent()!=null){
	    	String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" + SnakerHelper.convertXml(process.getContent());
	    	model = ModelParser.parse(xml.getBytes("UTF-8")) ;
    	}
    	return model;
    }
}